﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Collections.Specialized;
using System.Runtime.Serialization;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using log4net;
using EasyChat_Server.Log4net;
using System.Diagnostics;

namespace EasyChat_Server
{
    public partial class Form1 : Form
    {
        #region 字段定义

        bool listenBool = true;
        /// <summary>
        /// 本机ip
        /// </summary>
        //public IPAddress _ip = Dns.GetHostAddresses(Dns.GetHostName())[0];//可能有多个,此时的IP是本地IP
        static string ipString = System.Configuration.ConfigurationManager.AppSettings["IP"];
        IPAddress _ip = IPAddress.Parse(ipString);
        /// <summary>
        /// 服务器程序使用的端口，默认为8888
        /// </summary>
        public int _port = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["Port"]);

        /// <summary>
        /// 接收数据缓冲区大小64K 
        /// </summary>
        private const int _maxPacket = 64 * 1024;

        /// <summary>
        /// 服务器端的监听器
        /// </summary>
        private TcpListener _tcpl = null;

        /// <summary>
        /// 保存所有客户端会话的哈希表
        /// </summary>
        private Hashtable _transmit_tb = new Hashtable();


        #endregion

        public Form1()
        {
            InitializeComponent();
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            //  Listener listener = new Listener();
            listenBool = true;
            Thread listenThread = new Thread(StartUp);
            listenThread.IsBackground = true;
            try
            {
                //  listener.GetConfig();

                listenThread.Start();
                CheckForIllegalCrossThreadCalls = false;//不捕获对错误线程的调用
                this.label1.Text = string.Format("服务器已启动，正在监听...\n 服务器IP：{0}\t端口号：{1}\n", _ip, _port);
            }
            catch (Exception ex)
            {
                MessageBox.Show("\n服务器发生异常,消息：" + ex.Message);
                listenThread.Abort();
            }
        }


        #region 服务器方法

        /// <summary>
        /// 关闭监听器并释放资源
        /// </summary>
        public void ListenClose()
        {
            if (_tcpl != null)
            {
                _tcpl.Stop();//如果不为空 就停止 tcplistener
            }
            //关闭客户端连接并清理资源
            if (_transmit_tb.Count != 0)//客户端会话的哈希表
            {
                // 通知所有客户端服务器关闭
                foreach (DictionaryEntry de in _transmit_tb)
                {
                    string _clientName = de.Key as string;
                    Socket _clientSkt = de.Value as Socket;
                    _clientSkt.Send(Encoding.Unicode.GetBytes("服务器已关闭"));
                }
                foreach (Socket session in _transmit_tb.Values)
                {
                    session.Shutdown(SocketShutdown.Both);
                }

                _transmit_tb.Clear();
                _transmit_tb = null;
            }
        }



        ///// <summary>
        ///// 配置监听端口号 
        ///// </summary>
        //public void GetConfig()
        //{
        //    string portParam;
        //    Console.Write("请输入监听端口，直接回车则接受默认端口8888: ");
        //    //portParam = Console.ReadLine();
        //    portParam = Console.ReadLine();

        //    if (portParam != string.Empty)
        //    {
        //        if (!int.TryParse(portParam, out _port) || _port < 1023 || _port > 65535)//很是精炼的语句
        //        {
        //            _port = 8888;
        //            MessageBox.Show("端口号不合法,默认端口号被接受!");
        //        }
        //    }
        //}

        /// <summary>
        /// 序列化在线列表，向客户端返回序列化后的字节数组
        /// </summary>
        /// <returns>序列化后的字节数组</returns>
        private byte[] SerializeOnlineList()
        {
            StringCollection onlineList = new StringCollection();
            foreach (object o in _transmit_tb.Keys)
            {
                onlineList.Add(o as string);//转换语句
            }
            IFormatter format = new BinaryFormatter();//以二进制格式将对象或整个连接对
            //象图形序列化和反序列化。
            MemoryStream stream = new MemoryStream();//创建其支持存储区为内存的流
            format.Serialize(stream, onlineList);//保持到内存流
            byte[] ret = stream.ToArray();
            stream.Close();
            return ret;

        }
        /// <summary>
        /// 启动监听，轮询监听客户机请求并将客户端套接字存入转发表
        /// </summary>
        public void StartUp()
        {
            //IPAddress _ip = Dns.GetHostAddresses(Dns.GetHostName())[0];//可能有多个,此时的IP是本地IP
            try
            {
                _tcpl = new TcpListener(_ip, _port);
                _tcpl.Start();//开始侦听传入的连接请求。 
                ThreadPool.SetMaxThreads(1000, 100);
                int maxThreadNum, portThreadNum, workThreadNum, workportThreadNum;
                int minThreadNum;

                while (listenBool)
                {

                    Socket newClient = _tcpl.AcceptSocket();//本地TcpListener 接受新的请求 

                    ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadFunc), newClient);
                    ThreadPool.GetMaxThreads(out maxThreadNum, out portThreadNum);//out maxThreadNum, 
                    ThreadPool.GetMinThreads(out minThreadNum, out portThreadNum);
                    ThreadPool.GetAvailableThreads(out workThreadNum, out workportThreadNum);
                //    listBox1.Items.Add("活动线程数:" + maxThreadNum + "空闲线程数:" + workThreadNum + "--维护空闲线程数：" + minThreadNum);
                    //  listBox1.Items.Add("开启线程...");
                    listBox1.SelectedIndex = listBox1.Items.Count - 1;
                    CheckForIllegalCrossThreadCalls = false;//不捕获对错误线程的调用
                    //   Thread.Sleep(200);

                }
            }
            catch (Exception ex)
            {
                LogManager.GetLogger(typeof(Form1)).Error("错误信息:" + ex.Message);
                MessageBox.Show(ex.Message);
            }
        }

        private string DecodingBytes(byte[] s)
        {
            return string.Concat(s[0].ToString(), s[1].ToString());
        }
        /// <summary>
        /// 线程执行体,转发消息-------------------
        /// </summary>
        /// <param name="obj">传递给线程执行体的用户名，用以与用户通信</param>
        private void ThreadFunc(object obj)
        {
            //通过转发表得到当前用户套接字
            Socket clientSkt = obj as Socket;
            try
            {
                Thread.CurrentThread.IsBackground = true;
                clientSkt.SendTimeout = 5000;
                clientSkt.ReceiveTimeout = 5000;
                byte[] packetBuff = new byte[128];// 接收数据缓冲区大小64K 
                clientSkt.Receive(packetBuff);//将接受的远程SOCKET,将数据存入接受缓冲区
                string message = Encoding.UTF8.GetString(packetBuff).TrimEnd('\0');
                LogManager.GetLogger(typeof(Form1)).Info("请求信息:" + message);//将对数据库的操作写到log日志文件
                if (message.Length > 0)
                {
                    string udl = message.Substring(0, 4);
                    string data = message.Substring(8);
                    DAL.TestDAL test = new DAL.TestDAL();
                    string rusult = test.RunProc("[WP_CHARGE]", data, udl);
                    listBox1.Items.Add(message);
                    listBox1.SelectedIndex = listBox1.Items.Count - 1;
                    clientSkt.Send(Encoding.Default.GetBytes(rusult));
                    LogManager.GetLogger(typeof(Form1)).Info("响应信息:" + rusult);//将对数据库的操作写到log日志文件 
                }            
                clientSkt.Dispose();
                clientSkt.Close();
                //清理线程
                Thread.CurrentThread.DisableComObjectEagerCleanup();
            }
            catch (SocketException ea)
            {
                listBox1.Items.Add(ea.Message);
                LogManager.GetLogger(typeof(Form1)).Error("错误信息:" + ea.Message);
                clientSkt.Dispose();
                clientSkt.Close();
            }
            catch (Exception ex)
            {                
                LogManager.GetLogger(typeof(Form1)).Error("错误信息:" + ex.Message);
                listBox1.Items.Add(ex.Message);
                listBox1.SelectedIndex = listBox1.Items.Count - 1;
                clientSkt.Send(Encoding.Default.GetBytes(ex.Message));
                clientSkt.Dispose();
                clientSkt.Close();
                Thread.CurrentThread.Abort();
            }
        }

        #endregion

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            listenBool = false;
            ListenClose();//关闭socket
            Application.Exit();
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.listBox1.Items.Count >= 200)
            {
                this.listBox1.Items.Clear();
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            buttonStart_Click(sender, e);
            this.buttonStart.Enabled = false;
        }
    }
}
